/**
 * 
 */
package com.cap.bts.crmdp.webservice;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;

import com.cap.bts.crmdp.dealer.mars.domain.MarsLog;
import com.cap.bts.crmdp.dealer.mars.dto.MARSParamDto;
import com.cap.bts.crmdp.dealer.mars.dto.MessageNumDto;
import com.cap.bts.crmdp.dealer.mars.service.IMarsLogService;
import com.cap.bts.crmdp.dealer.mars.service.IMarsMemberPackageService;
import com.cap.bts.crmdp.dealer.mars.service.IMarsRedemptionService;
import com.cap.bts.crmdp.dealer.purchase.domain.MemberPackageInfo;
import com.cap.bts.crmdp.mars.util.LogTask;
import com.cap.bts.crmdp.mars.util.ThreadPoolUtil;
import com.cap.bts.crmdp.webservice.dto.WSCrmCancelOrderResultDto;
import com.cap.bts.crmdp.webservice.dto.WSCrmCustomerDto;
import com.cap.bts.crmdp.webservice.dto.WSCrmCustomerResultDto;
import com.cap.bts.crmdp.webservice.dto.WSCrmOrderDto;
import com.cap.bts.crmdp.webservice.dto.WSCrmSettlementDto;
import com.cap.bts.crmdp.webservice.dto.WSCrmSettlementResultDto;
import com.cap.bts.framework.common.exception.AppException;
import com.cap.bts.framework.common.util.ApplicationContextUtil;

/**
 * @author annson
 *
 */
public class WSCrmFacade {

	private static final Logger LOGGER = Logger.getLogger(WSCrmFacade.class);

	
	/**
	 * 
	 * @param xmlText
	 * @return
	 */
	public String mars(String paramText) {
		
		StringBuilder returnXmlText = new StringBuilder();
		MarsLog marsLog = new MarsLog("webServices");
		marsLog.setSuccessFlag("success");		
		marsLog.setParamText(paramText);

		LOGGER.info(paramText);
		
		MARSParamDto paramDto = null;
		try {

			paramDto = buildParamFromXml(paramText);
			
			//todo validation token
			String token = paramDto.getToken();
			String method = paramDto.getMethod();
			
			marsLog.setCallMethod(method);
			
			if(false){
				
				returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
				returnXmlText.append("<statusCode>0</statusCode>");
				returnXmlText.append("<resultMessage>unauthorized</resultMessage>");
				returnXmlText.append("</root>");
				
				marsLog.setSuccessFlag("failure");
				
			}else if("CUSTOMER".equals(method)){
				WSCrmCustomerDto dto = new WSCrmCustomerDto(false);
				
				dto.setCustomerId(paramDto.getCustomerId());
				dto.setCustomerName(paramDto.getCustomerName());
				dto.setMobilePhone(paramDto.getMobilePhone());
				dto.setCarPlate(paramDto.getCarPlate());
				dto.setCarId(paramDto.getCarId());
				dto.setServerCenter(paramDto.getServerCenter());
				
				WSCrmCustomerResultDto resultDto = null;
				if(StringUtils.isBlank(paramDto.getCustomerId())
						|| StringUtils.isBlank(paramDto.getMobilePhone())
						|| StringUtils.isBlank(paramDto.getServerCenter())
						|| (StringUtils.isNotBlank(paramDto.getCarId())
								&& StringUtils.isBlank(paramDto.getCarPlate()))
						){
					resultDto = new WSCrmCustomerResultDto();
					resultDto.setStatusCode("0");
					resultDto.setResultMessage("缺失必要参数");
				}else{
					resultDto = new CrmFacade().processCustomerInfo(dto);
				}
				marsLog.setSuccessFlag("1".equals(resultDto.getStatusCode()) ? "success" : "failure");
				
				
				returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
				returnXmlText.append("<statusCode>").append(resultDto.getStatusCode()).append("</statusCode>");
				returnXmlText.append("<resultMessage>").append(StringUtils.defaultString(resultDto.getResultMessage())).append("</resultMessage>");
				returnXmlText.append("</root>");
			}else if("CANCELORDER".equals(method)){
				
				LOGGER.info("CANCELORDER......");
				WSCrmOrderDto dto = new WSCrmOrderDto();
				dto.setCouponList(paramDto.getCoupons());
				dto.setCouponList2(paramDto.getCoupons2());
				dto.setTransType(paramDto.getTransType());
				dto.setSoNumber(paramDto.getSoNumber());
				dto.setCardNumberList(paramDto.getCardNumbers());
				
				WSCrmCancelOrderResultDto resultDto = new CrmFacade().cancelOrder(dto);
				
				marsLog.setSuccessFlag("1".equals(resultDto.getStatusCode()) ? "success" : "failure");
				
				returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
				returnXmlText.append("<statusCode>").append(resultDto.getStatusCode()).append("</statusCode>");
				returnXmlText.append("<resultMessage>").append(StringUtils.defaultString(resultDto.getResultMessage())).append("</resultMessage>");
				returnXmlText.append("</root>");
				
				
			}else if("DELETEORDERCHECK".equals(method)){
				
				LOGGER.info("DELETEORDERCHECK......");
				WSCrmOrderDto dto = new WSCrmOrderDto();
				dto.setCouponList(paramDto.getCoupons());
				dto.setCouponList2(paramDto.getCoupons2());
				dto.setTransType(paramDto.getTransType());
				dto.setSoNumber(paramDto.getSoNumber());
				dto.setCardNumberList(paramDto.getCardNumbers());
				
				//todo 判断订单中所购买套餐是否有使用过
				boolean userdFlag = false;
				StringBuilder usedPackageNumber = new StringBuilder();
				if(!dto.getCardNumberList().isEmpty()){
					IMarsMemberPackageService marsMemberPackageService = (IMarsMemberPackageService)ApplicationContextUtil.getBean("marsMemberPackageServiceImpl");
					
					for(String packageNumber : dto.getCardNumberList()){
						long usedCount = marsMemberPackageService.getUsedRedemptionCountByPackageNumber(packageNumber);
						if(usedCount > 0){
							userdFlag = true;
							usedPackageNumber.append(packageNumber).append(".");
						}
					}
					
				}
				if(userdFlag){
					marsLog.setSuccessFlag("failure");
					
					returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
					returnXmlText.append("<statusCode>0</statusCode>");
					returnXmlText.append("<resultMessage>").append(usedPackageNumber.toString()).append("套餐已使用，不能退卡.</resultMessage>");
					returnXmlText.append("</root>");
				}else{
					
					marsLog.setSuccessFlag("success");
					
					returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
					returnXmlText.append("<statusCode>1</statusCode>");
					returnXmlText.append("<resultMessage>").append(StringUtils.defaultString("success")).append("</resultMessage>");
					returnXmlText.append("</root>");
				}
				
				
			}else if("DELETEORDER".equals(method)){
				
				LOGGER.info("DELETEORDER......");
				WSCrmOrderDto dto = new WSCrmOrderDto();
				dto.setCouponList(paramDto.getCoupons());
				dto.setCouponList2(paramDto.getCoupons2());
				dto.setTransType(paramDto.getTransType());
				dto.setSoNumber(paramDto.getSoNumber());
				dto.setCardNumberList(paramDto.getCardNumbers());
				
				
				//todo 判断订单中所购买套餐是否有使用过
				boolean userdFlag = false;
				StringBuilder usedPackageNumber = new StringBuilder();
				IMarsMemberPackageService marsMemberPackageService = (IMarsMemberPackageService)ApplicationContextUtil.getBean("marsMemberPackageServiceImpl");
				if(!dto.getCardNumberList().isEmpty()){
					
					for(String packageNumber : dto.getCardNumberList()){
						long usedCount = marsMemberPackageService.getUsedRedemptionCountByPackageNumber(packageNumber);
						if(usedCount > 0){
							userdFlag = true;
							usedPackageNumber.append(packageNumber).append(".");
						}
					}
					
				}
				if(userdFlag){
					marsLog.setSuccessFlag("failure");
					
					returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
					returnXmlText.append("<statusCode>0</statusCode>");
					returnXmlText.append("<resultMessage>").append(usedPackageNumber.toString()).append("已使用，拒绝退单操作.</resultMessage>");
					returnXmlText.append("</root>");
				}else{
					List<Long> memberIdList = new ArrayList<Long>();
					for(String packageNumber : dto.getCardNumberList()){
						MemberPackageInfo memberPackageInfo = marsMemberPackageService.getPackageInfoByPackageNumber(packageNumber);
						
						//状态为已激活，需要处理入会礼
						if(memberPackageInfo != null && memberPackageInfo.getStatus() == 2){
							memberIdList.add(memberPackageInfo.getActiveMemberId());
						}
					}
					
					WSCrmCancelOrderResultDto resultDto = new CrmFacade().cancelOrder(dto);
					
					marsLog.setSuccessFlag("1".equals(resultDto.getStatusCode()) ? "success" : "failure");
					
					if("1".equals(resultDto.getStatusCode())){
						//删除入会礼，状态为已激活
						for(Long memberId : memberIdList){
							try{
								marsMemberPackageService.deleteOrderGift(memberId);
							}catch(Exception e){
								LOGGER.error("", e);
							}
						}
					}
					
					returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
					returnXmlText.append("<statusCode>").append(resultDto.getStatusCode()).append("</statusCode>");
					returnXmlText.append("<resultMessage>").append(StringUtils.defaultString(resultDto.getResultMessage())).append("</resultMessage>");
					returnXmlText.append("</root>");
				}
				
				
				
				
				
			}else if("SETTLEMENT".equals(method)){
				LOGGER.info("SETTLEMENT......");
				
				WSCrmSettlementDto dto = new WSCrmSettlementDto();
				
				dto.setTransType(paramDto.getTransType());
				dto.setCouponList(paramDto.getCoupons());
				dto.setCouponList2(paramDto.getCoupons2());
				dto.setSoNumber(paramDto.getSoNumber());
				dto.setCardNumberList(paramDto.getCardNumbers());
				
				
				WSCrmSettlementResultDto resultDto = new CrmFacade().settlement(dto);
				marsLog.setSuccessFlag("1".equals(resultDto.getStatusCode()) ? "success" : "failure");
				
				returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
				returnXmlText.append("<statusCode>").append(resultDto.getStatusCode()).append("</statusCode>");
				returnXmlText.append("<resultMessage>").append(StringUtils.defaultString(resultDto.getResultMessage())).append("</resultMessage>");
				returnXmlText.append("<activation>").append(resultDto.getActivation()).append("</activation>");
				returnXmlText.append("</root>");
				
			}else if("SMSCOUNT".equals(method)){
				LOGGER.info("SMSCOUNT......");
				
				String strDealerId = paramDto.getServerCenter();
				
				Long dealerId = Long.parseLong(strDealerId);
				
				IMarsRedemptionService IMarsRedemptionService = (IMarsRedemptionService)ApplicationContextUtil.getBean("marsRedemptionServiceImpl");
				
				MessageNumDto messageNumDto = null;
				String statusCode = "1";
				String resultMessage = "";
				try {
					messageNumDto = IMarsRedemptionService.getNumberAboutMessage(dealerId, paramDto.getDate());
					marsLog.setSuccessFlag("success");
				} catch (AppException e) {
					statusCode = "0";
					marsLog.setSuccessFlag("failure");
					resultMessage = e.getMessage();
					LOGGER.error("", e);
				}
				
				if(messageNumDto == null ){
					messageNumDto = new MessageNumDto();
				}
				
				
				returnXmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>");
				returnXmlText.append("<statusCode>").append(statusCode).append("</statusCode>");
				returnXmlText.append("<resultMessage>").append(StringUtils.defaultString(resultMessage)).append("</resultMessage>");
				returnXmlText.append("<initNumber>").append(StringUtils.defaultString(messageNumDto.getInitNumber())).append("</initNumber>");
				returnXmlText.append("<sendNumber>").append(StringUtils.defaultString(messageNumDto.getSendNumber())).append("</sendNumber>");
				returnXmlText.append("<rechargeNumber>").append(StringUtils.defaultString(messageNumDto.getRechargeNumber())).append("</rechargeNumber>");
				returnXmlText.append("<balanceNumber>").append(StringUtils.defaultString(messageNumDto.getBalanceNumber())).append("</balanceNumber>");
				returnXmlText.append("<todayNumber>").append(StringUtils.defaultString(messageNumDto.getTodayNumber())).append("</todayNumber>");
				returnXmlText.append("</root>");
				
			}else{
				marsLog.setSuccessFlag("failure");
				marsLog.setDescp("method error.");
			}
	        
		} catch (Exception e) {
			LOGGER.error("", e);
			marsLog.setSuccessFlag("failure");
			marsLog.setDescp(e.getMessage());
		}
		
		marsLog.setReturnText(returnXmlText.toString());
		
		ThreadPoolUtil.execute(new LogTask(marsLog));
		
		return returnXmlText.toString();
	}

	
	
	private MARSParamDto buildParamFromXml(String xmlText) throws DocumentException{
		MARSParamDto dto = new MARSParamDto();
		
		
		Document document = DocumentHelper.parseText(xmlText);
		Element rootElement = document.getRootElement();
		
		
		dto.setToken(getNodeValue(rootElement, "token"));
		dto.setMethod(getNodeValue(rootElement, "method"));
		dto.setCustomerId(getNodeValue(rootElement, "customerId"));
		dto.setCustomerName(getNodeValue(rootElement, "customerName"));
		dto.setMobilePhone(getNodeValue(rootElement, "mobilePhone"));
		dto.setSoNumber(getNodeValue(rootElement, "soNumber"));
		dto.setCarId(getNodeValue(rootElement, "carId"));
		dto.setCarPlate(getNodeValue(rootElement, "carPlate"));
		dto.setServerCenter(getNodeValue(rootElement, "serverCenter"));
		dto.setTransType(getNodeValue(rootElement, "transType"));
		dto.setDate(getNodeValue(rootElement, "date"));
		
		List<Node> cardNumberNodes = rootElement.selectNodes("cards/cardNumber");
		if(cardNumberNodes != null && cardNumberNodes.size() == 1){
			dto.setCardNumber(getNodeValue(cardNumberNodes.get(0)));
			dto.getCardNumbers().add(getNodeValue(cardNumberNodes.get(0)));
		}else if(cardNumberNodes.size() > 1){
			for(Node node : cardNumberNodes){
				dto.getCardNumbers().add(getNodeValue(node));
			}
		}
		
		List<Node> couponNodes = rootElement.selectNodes("coupons/couponNo");
		if(cardNumberNodes != null){
			for(Node node : couponNodes){
				dto.getCoupons().add(getNodeValue(node));
			}
		}
		
		List<Node> couponNodes2 = rootElement.selectNodes("coupons2/couponNo");
		if(cardNumberNodes != null){
			for(Node node : couponNodes2){
				dto.getCoupons2().add(getNodeValue(node));
			}
		}
		
		
		
		return dto;
	}
	
	private String getNodeValue(Node node){
		if(node != null){
			return node.getText();
		}
		
		return null;
	}
	private String getNodeValue(Node rootElement, String select){
		Node node = rootElement.selectSingleNode(select);
		if(node != null){
			return node.getText();
		}
		
		return null;
	}

}
